package com.gan.simple_init.common.exception;


import com.gan.simple_init.common.base.ResponseErrorEnum;
import com.gan.simple_init.common.base.ResponseResult;
import com.gan.simple_init.common.base.RestResultGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;

/**
 * 全局异常处理器
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(BusinessException.class)
    public ResponseResult<?> businessExceptionHandler(BusinessException e) {
        log.error("BusinessException", e);
        return RestResultGenerator.error(e.getCode(), e.getMessage());
    }

    @ExceptionHandler(RuntimeException.class)
    public ResponseResult<?> runtimeExceptionHandler(RuntimeException e) {
        log.error("RuntimeException", e);
        return RestResultGenerator.error(ResponseErrorEnum.SYSTEM_ERROR, "系统错误");
    }

    /**
     * 校验错误拦截处理
     *
     * @param exception 错误信息集合
     * @return 错误信息
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseResult<?> validationBodyException(MethodArgumentNotValidException exception) {
        BindingResult result = exception.getBindingResult();
        if (result.hasErrors()) {
            List<ObjectError> errors = result.getAllErrors();
            FieldError fieldError = (FieldError) errors.get(0);

            log.error("对象校验失败 : 对象{" + fieldError.getObjectName() + "},字段{" + fieldError.getField() +
                    "},错误信息{" + fieldError.getDefaultMessage() + "}");
            // fieldError.getDefaultMessage()为实体类中的message
            return RestResultGenerator.error(fieldError.getDefaultMessage());
        }
        return null;
    }

    /**
     * 参数类型转换错误
     *
     * @param exception 错误
     * @return 错误信息
     */
    @ExceptionHandler(HttpMessageConversionException.class)
    public ResponseResult<?> parameterTypeException(HttpMessageConversionException exception) {
        log.error(exception.getCause().getLocalizedMessage());
        return RestResultGenerator.error(ResponseErrorEnum.CAST_ERROR);
    }

    /**
     * 用户权限不足时选择继续抛出给 Security 处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(AccessDeniedException.class)
    public ResponseResult<?> accessDeniedExceptionHandler(AccessDeniedException e) {
        throw e;
    }
}
